import type { AxiosResponse } from 'axios'

/**
 * dataURLtoBlob
 *
 * @see https://github.com/blueimp/JavaScript-Canvas-to-Blob
 */
const dataURLPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/
export function getBlobByDataURL(dataURL: string) {
  const matches = dataURL.match(dataURLPattern)
  if (!matches) {
    throw new Error('invalid data URI')
  }

  const mediaType = matches[2] ? matches[1] : `text/plain${matches[3] || ''}`
  const isBase64 = !!matches[4]
  const dataString = dataURL.slice(matches[0].length)

  const byteString = isBase64
    ? atob(dataString)
    : decodeURIComponent(dataString)

  const byteStringLen = byteString.length
  const arrayBuffer = new ArrayBuffer(byteStringLen)
  const intArray = new Uint8Array(arrayBuffer)

  for (let i = 0; i < byteStringLen; i += 1) {
    intArray[i] = byteString.charCodeAt(i)
  }

  return new Blob([intArray], {
    type: mediaType,
  })
}

export function getBlobByUrl(url: string): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url, true)
    xhr.responseType = 'blob'
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(xhr.response)
      }
      else {
        reject(new Error(`Failed to load blob: ${xhr.statusText}`))
      }
    }
    xhr.onerror = () => {
      reject(new Error('Failed to load blob'))
    }
    xhr.send()
  })
}

export function saveAs(blob: Blob, filename: string) {
  const a = document.createElement('a')
  const url = URL.createObjectURL(blob)
  a.href = url
  a.download = filename
  a.click()
  URL.revokeObjectURL(url)
}

export async function downloadByResponse(response: AxiosResponse) {
  return new Promise((resolve, reject) => {
    try {
      const blob = response.data
      const contentDisposition = response.headers['content-disposition']
      let filename = ''

      const matches = contentDisposition.match(/filename\*=utf-8''([^;]*)/)
      if (matches != null && matches[1]) {
        filename = decodeURIComponent(matches[1].replace(/['"]/g, ''))
      }
      else {
        const matches2 = decodeURIComponent(contentDisposition).match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
        if (matches2 != null && matches2[1]) {
          filename = matches2[1].replace(/['"]/g, '')
        }
      }
      saveAs(blob, filename)

      resolve(true)
    }
    catch (error: any) {
      console.log('error>>>>', error)
      reject(new Error(error?.message ?? '未知错误'))
    }
  })
}

export async function downloadByUrl(url: string, filename: string) {
  const blob = await getBlobByUrl(url)
  const match = /\.[^.]+$/.exec(url)
  const suffix = match ? match[0] : ''
  const blobFilename = filename.endsWith(suffix) ? filename : `${filename}${suffix}`
  saveAs(blob, blobFilename)
}
